Форматированный ввод
====================


В языке D можно определить формат данных, которые ожидаются при вводе.
Формат определяет как данные, которые должны быть прочитаны, так и символы, которые следует
игнорировать.Спецификаторы формата ввода D аналогичны тем, которые присутствуют в языке C.
Как мы уже использовали в предыдущих главах, спецификатор формата "
%s" считывает данные в соответствии с типом переменной. Например, поскольку тип
следующей переменной - double, символы на входе будут считываться как
число с плавающей запятой:

.. code-block:: d

    double number;
    readf(" %s", &number);

Строка формата может содержать следующие спецификации:

* Символ пробела: указывает ноль или более пробельных символов при
  вводе и указывает, что все эти символы должны быть прочитаны и проигнорированы.
* Спецификатор формата: Аналогично спецификаторам выходного формата, спецификаторы входного формата
  начинаются с символа % и определяют формат данных, которые
  должны быть загружены.
* Любой другой символ: Указывает символы, которые ожидаются при вводе как
  есть, которые следует читать и игнорировать.
  Строка формата позволяет выбрать конкретную информацию из входных данных
  и игнорируйте остальные.
  Давайте посмотрим на пример, в котором используются все три типа информации в
  строке формата. Давайте предположим, что ожидается, что номер учащегося и оценка будут
  отображаться на входе в следующем формате:

.. code-block:: console

        number:123 grade:90

Давайте далее предположим, что теги number: и grade: должны игнорироваться. В
следующей строке формата будут выбраны значения number и grade и будут
проигнорированы остальные символы:

.. code-block:: d

    int number;
    int grade;
    readf("number:%s grade:%s", &number, &grade);

Символы, выделенные в "number:%s grade:%s", должны отображаться при
вводе точно так, как указано; readf() считывает и игнорирует их.
Единственный символ пробела, который появляется в приведенной выше строке формата, приведет
к тому, что все пробельные символы, которые появляются точно в этой позиции, будут прочитаны и
проигнорированы.
Поскольку символ % имеет особое значение в строках формата, когда
сам этот символ должен быть прочитан и проигнорирован, он должен быть дважды записан в строке формата
как %%. Чтение одной строки данных из входных данных было рекомендовано как
strip(чтение()) в главе "Строки" (стр. 75). Вместо этого метода символ \n
в конце строки формата может достичь аналогичной цели:

.. code-block:: d

    import std.stdio;

    void main()
    {
        write("First name: ");
        string firstName;
        readf(" %s\n", &firstName); // ← \n в конце строки
        write("Last name : ");
        string lastName;
        readf(" %s\n", &lastName); // ← \n в конце строки
        write("Age : ");
        int age;
        readf(" %s", &age);
        writefln("%s %s (%s)", firstName, lastName, age);
    }


Символы \n в концах строк формата при чтении имени и
фамилии приведут к тому, что символы новой строки будут считываться из входных данных и
игнорироваться. Однако потенциальные пробельные символы в концах строк
, возможно, все еще потребуется удалить с помощью strip().

Символы спецификатора формата
-----------------------------

Способ считывания данных задается следующими
символами спецификатора формата:
d: Считывание целого числа в десятичной системе.
o: Считывание целого числа в восьмеричной системе.
x: Считывание целого числа в шестнадцатеричной системе.
f: Считывает число с плавающей запятой.
s: Считывает в соответствии с типом переменной. Это наиболее часто используемый
спецификатор.
c: Считывает один символ. Этот спецификатор также позволяет считывать пробельные символы
. (Это отменяет поведение игнорирования.)
Например, если входные данные содержат "23 23 23", значения будут считаны
по-разному в соответствии с различными спецификаторами формата:

.. code-block:: d

    int number_d;
    int number_o;
    int number_x;
    readf(" %d %o %x", &number_d, &number_o, &number_x);
    writeln("Читать с %d: ", number_d);
    writeln("Читать с %o: ", number_o);
    writeln("Читать с %x: ", number_x);

Хотя входные данные содержат три набора символов "23", значения
переменных различны:

.. code-block:: console

    Read with %d: 23
    Read with %o: 19
    Read with %x: 35

Упражнение
----------

Предположим, что входные данные содержат дату в формате год.месяц.день. Напишите
программу, которая выводит число месяца. Например, если входные данные
2009.09.30, на выходе должно быть 9.
